home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / osi / isode / dosisode / DOSISODE80.ZIP / ISODE8.WRK / UNIX / LIB / DNS / GETHOSTN.C next >
Encoding:
C/C++ Source or Header  |  1991-12-16  |  9.6 KB  |  421 lines

  1. #include <fiddle.h>
  2. #define _PATH_HOSTS "/etc/hosts"
  3. /*
  4.  * Copyright (c) 1985, 1988 Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms are permitted
  8.  * provided that: (1) source distributions retain this entire copyright
  9.  * notice and comment, and (2) distributions including binaries display
  10.  * the following acknowledgement:  ``This product includes software
  11.  * developed by the University of California, Berkeley and its contributors''
  12.  * in the documentation or other materials provided with the distribution
  13.  * and in all advertising materials mentioning features or use of this
  14.  * software. Neither the name of the University nor the names of its
  15.  * contributors may be used to endorse or promote products derived
  16.  * from this software without specific prior written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  19.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #if defined(LIBC_SCCS) && !defined(lint)
  23. static char sccsid[] = "@(#)gethostnamadr.c    6.41 (Berkeley) 6/1/90";
  24. #endif /* LIBC_SCCS and not lint */
  25.  
  26. #include <sys/param.h>
  27. #include <sys/socket.h>
  28. #include <netinet/in.h>
  29. #include <ctype.h>
  30. #include <netdb.h>
  31. #include <stdio.h>
  32. #include <errno.h>
  33. #include <arpa/inet.h>
  34. #include <arpa/nameser.h>
  35. #include <resolv.h>
  36.  
  37. #define    MAXALIASES    35
  38. #define    MAXADDRS    35
  39.  
  40. static char *h_addr_ptrs[MAXADDRS + 1];
  41.  
  42. static struct hostent host;
  43. static char *host_aliases[MAXALIASES];
  44. static char hostbuf[BUFSIZ+1];
  45. static struct in_addr host_addr;
  46. static FILE *hostf = NULL;
  47. static char hostaddr[MAXADDRS];
  48. static char *host_addrs[2];
  49. static int stayopen = 0;
  50. char *strpbrk();
  51.  
  52. #if PACKETSZ > 1024
  53. #define    MAXPACKET    PACKETSZ
  54. #else
  55. #define    MAXPACKET    1024
  56. #endif
  57.  
  58. typedef union {
  59.     HEADER hdr;
  60.     u_char buf[MAXPACKET];
  61. } querybuf;
  62.  
  63. typedef union {
  64.     long al;
  65.     char ac;
  66. } align;
  67.  
  68.  
  69. extern int h_errno;
  70. extern errno;
  71.  
  72. static struct hostent *
  73. getanswer(answer, anslen, iquery)
  74.     querybuf *answer;
  75.     int anslen;
  76.     int iquery;
  77. {
  78.     register HEADER *hp;
  79.     register u_char *cp;
  80.     register int n;
  81.     u_char *eom;
  82.     char *bp, **ap;
  83.     int type, class, buflen, ancount, qdcount;
  84.     int haveanswer, getclass = C_ANY;
  85.     char **hap;
  86.  
  87.     eom = answer->buf + anslen;
  88.     /*
  89.      * find first satisfactory answer
  90.      */
  91.     hp = &answer->hdr;
  92.     ancount = ntohs(hp->ancount);
  93.     qdcount = ntohs(hp->qdcount);
  94.     bp = hostbuf;
  95.     buflen = sizeof(hostbuf);
  96.     cp = answer->buf + sizeof(HEADER);
  97.     if (qdcount) {
  98.         if (iquery) {
  99.             if ((n = dn_expand((char *)answer->buf, eom,
  100.                  cp, bp, buflen)) < 0) {
  101.                 h_errno = NO_RECOVERY;
  102.                 return ((struct hostent *) NULL);
  103.             }
  104.             cp += n + QFIXEDSZ;
  105.             host.h_name = bp;
  106.             n = strlen(bp) + 1;
  107.             bp += n;
  108.             buflen -= n;
  109.         } else
  110.             cp += dn_skipname(cp, eom) + QFIXEDSZ;
  111.         while (--qdcount > 0)
  112.             cp += dn_skipname(cp, eom) + QFIXEDSZ;
  113.     } else if (iquery) {
  114.         if (hp->aa)
  115.             h_errno = HOST_NOT_FOUND;
  116.         else
  117.             h_errno = TRY_AGAIN;
  118.         return ((struct hostent *) NULL);
  119.     }
  120.     ap = host_aliases;
  121.     *ap = NULL;
  122.     host.h_aliases = host_aliases;
  123.     hap = h_addr_ptrs;
  124.     *hap = NULL;
  125. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  126.     host.h_addr_list = h_addr_ptrs;
  127. #endif
  128.     haveanswer = 0;
  129.     while (--ancount >= 0 && cp < eom) {
  130.         if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0)
  131.             break;
  132.         cp += n;
  133.         type = _getshort(cp);
  134.          cp += sizeof(u_short);
  135.         class = _getshort(cp);
  136.          cp += sizeof(u_short) + sizeof(u_long);
  137.         n = _getshort(cp);
  138.         cp += sizeof(u_short);
  139.         if (type == T_CNAME) {
  140.             cp += n;
  141.             if (ap >= &host_aliases[MAXALIASES-1])
  142.                 continue;
  143.             *ap++ = bp;
  144.             n = strlen(bp) + 1;
  145.             bp += n;
  146.             buflen -= n;
  147.             continue;
  148.         }
  149.         if (iquery && type == T_PTR) {
  150.             if ((n = dn_expand((char *)answer->buf, eom,
  151.                 cp, bp, buflen)) < 0) {
  152.                 cp += n;
  153.                 continue;
  154.             }
  155.             cp += n;
  156.             host.h_name = bp;
  157.             return(&host);
  158.         }
  159.         if (iquery || type != T_A)  {
  160. #ifdef DEBUG
  161.             if (_res.options & RES_DEBUG)
  162.                 printf("unexpected answer type %d, size %d\n",
  163.                     type, n);
  164. #endif
  165.             cp += n;
  166.             continue;
  167.         }
  168.         if (haveanswer) {
  169.             if (n != host.h_length) {
  170.                 cp += n;
  171.                 continue;
  172.             }
  173.             if (class != getclass) {
  174.                 cp += n;
  175.                 continue;
  176.             }
  177.         } else {
  178.             host.h_length = n;
  179.             getclass = class;
  180.             host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
  181.             if (!iquery) {
  182.                 host.h_name = bp;
  183.                 bp += strlen(bp) + 1;
  184.             }
  185.         }
  186.  
  187.         bp += sizeof(align) - ((u_long)bp % sizeof(align));
  188.  
  189.         if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
  190. #ifdef DEBUG
  191.             if (_res.options & RES_DEBUG)
  192.                 printf("size (%d) too big\n", n);
  193. #endif
  194.             break;
  195.         }
  196.         bcopy(cp, *hap++ = bp, n);
  197.         bp +=n;
  198.         cp += n;
  199.         haveanswer++;
  200.     }
  201.     if (haveanswer) {
  202.         *ap = NULL;
  203. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  204.         *hap = NULL;
  205. #else
  206.         host.h_addr = h_addr_ptrs[0];
  207. #endif
  208.         return (&host);
  209.     } else {
  210.         h_errno = TRY_AGAIN;
  211.         return ((struct hostent *) NULL);
  212.     }
  213. }
  214.  
  215. struct hostent *
  216. gethostbyname(name)
  217.     char *name;
  218. {
  219.     querybuf buf;
  220.     register char *cp;
  221.     int n;
  222.     extern struct hostent *_gethtbyname();
  223.  
  224.     /*
  225.      * disallow names consisting only of digits/dots, unless
  226.      * they end in a dot.
  227.      */
  228.     if (isdigit(name[0]))
  229.         for (cp = name;; ++cp) {
  230.             if (!*cp) {
  231.                 if (*--cp == '.')
  232.                     break;
  233.                 /*
  234.                  * All-numeric, no dot at the end.
  235.                  * Fake up a hostent as if we'd actually
  236.                  * done a lookup.  What if someone types
  237.                  * 255.255.255.255?  The test below will
  238.                  * succeed spuriously... ???
  239.                  */
  240.                 if ((host_addr.s_addr = inet_addr(name)) == -1) {
  241.                     h_errno = HOST_NOT_FOUND;
  242.                     return((struct hostent *) NULL);
  243.                 }
  244.                 host.h_name = name;
  245.                 host.h_aliases = host_aliases;
  246.                 host_aliases[0] = NULL;
  247.                 host.h_addrtype = AF_INET;
  248.                 host.h_length = sizeof(u_long);
  249.                 h_addr_ptrs[0] = (char *)&host_addr;
  250.                 h_addr_ptrs[1] = (char *)0;
  251. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  252.                 host.h_addr_list = h_addr_ptrs;
  253. #else
  254.                 host.h_addr = h_addr_ptrs[0];
  255. #endif
  256.                 return (&host);
  257.             }
  258.             if (!isdigit(*cp) && *cp != '.')
  259.                 break;
  260.         }
  261.     if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
  262. #ifdef DEBUG
  263.         if (_res.options & RES_DEBUG)
  264.             printf("res_search failed\n");
  265. #endif
  266. /*        if (errno == ECONNREFUSED)
  267.             return (_gethtbyname(name));
  268.         else
  269.             return ((struct hostent *) NULL);*/
  270.         return (_gethtbyname(name));
  271.     }
  272.     return (getanswer(&buf, n, 0));
  273. }
  274.  
  275. struct hostent *
  276. gethostbyaddr(addr, len, type)
  277.     char *addr;
  278.     int len, type;
  279. {
  280.     int n;
  281.     querybuf buf;
  282.     register struct hostent *hp;
  283.     char qbuf[MAXDNAME];
  284.     extern struct hostent *_gethtbyaddr();
  285.  
  286.     if (type != AF_INET)
  287.         return ((struct hostent *) NULL);
  288.     (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
  289.         ((unsigned)addr[3] & 0xff),
  290.         ((unsigned)addr[2] & 0xff),
  291.         ((unsigned)addr[1] & 0xff),
  292.         ((unsigned)addr[0] & 0xff));
  293.     n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
  294.     if (n < 0) {
  295. #ifdef DEBUG
  296.         if (_res.options & RES_DEBUG)
  297.             printf("res_query failed\n");
  298. #endif
  299. /*        if (errno == ECONNREFUSED)
  300.             return (_gethtbyaddr(addr, len, type));
  301.         return ((struct hostent *) NULL);*/
  302.         return (_gethtbyaddr(addr, len, type));
  303.     }
  304.     hp = getanswer(&buf, n, 1);
  305.     if (hp == NULL)
  306.         return ((struct hostent *) NULL);
  307.     hp->h_addrtype = type;
  308.     hp->h_length = len;
  309.     h_addr_ptrs[0] = (char *)&host_addr;
  310.     h_addr_ptrs[1] = (char *)0;
  311.     host_addr = *(struct in_addr *)addr;
  312. #if BSD < 43 && !defined(h_addr)    /* new-style hostent structure */
  313.     hp->h_addr = h_addr_ptrs[0];
  314. #endif
  315.     return(hp);
  316. }
  317.  
  318. _sethtent(f)
  319.     int f;
  320. {
  321.     if (hostf == NULL)
  322.         hostf = fopen(_PATH_HOSTS, "r" );
  323.     else
  324.         rewind(hostf);
  325.     stayopen |= f;
  326. }
  327.  
  328. _endhtent()
  329. {
  330.     if (hostf && !stayopen) {
  331.         (void) fclose(hostf);
  332.         hostf = NULL;
  333.     }
  334. }
  335.  
  336. struct hostent *
  337. _gethtent()
  338. {
  339.     char *p;
  340.     register char *cp, **q;
  341.  
  342.     if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL)
  343.         return (NULL);
  344. again:
  345.     if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
  346.         return (NULL);
  347.     if (*p == '#')
  348.         goto again;
  349.     cp = strpbrk(p, "#\n");
  350.     if (cp == NULL)
  351.         goto again;
  352.     *cp = '\0';
  353.     cp = strpbrk(p, " \t");
  354.     if (cp == NULL)
  355.         goto again;
  356.     *cp++ = '\0';
  357.     /* THIS STUFF IS INTERNET SPECIFIC */
  358. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  359.     host.h_addr_list = host_addrs;
  360. #endif
  361.     host.h_addr = hostaddr;
  362.     *((u_long *)host.h_addr) = inet_addr(p);
  363.     host.h_length = sizeof (u_long);
  364.     host.h_addrtype = AF_INET;
  365.     while (*cp == ' ' || *cp == '\t')
  366.         cp++;
  367.     host.h_name = cp;
  368.     q = host.h_aliases = host_aliases;
  369.     cp = strpbrk(cp, " \t");
  370.     if (cp != NULL)
  371.         *cp++ = '\0';
  372.     while (cp && *cp) {
  373.         if (*cp == ' ' || *cp == '\t') {
  374.             cp++;
  375.             continue;
  376.         }
  377.         if (q < &host_aliases[MAXALIASES - 1])
  378.             *q++ = cp;
  379.         cp = strpbrk(cp, " \t");
  380.         if (cp != NULL)
  381.             *cp++ = '\0';
  382.     }
  383.     *q = NULL;
  384.     return (&host);
  385. }
  386.  
  387. struct hostent *
  388. _gethtbyname(name)
  389.     char *name;
  390. {
  391.     register struct hostent *p;
  392.     register char **cp;
  393.  
  394.     _sethtent(0);
  395.     while (p = _gethtent()) {
  396.         if (strcasecmp(p->h_name, name) == 0)
  397.             break;
  398.         for (cp = p->h_aliases; *cp != 0; cp++)
  399.             if (strcasecmp(*cp, name) == 0)
  400.                 goto found;
  401.     }
  402. found:
  403.     _endhtent();
  404.     return (p);
  405. }
  406.  
  407. struct hostent *
  408. _gethtbyaddr(addr, len, type)
  409.     char *addr;
  410.     int len, type;
  411. {
  412.     register struct hostent *p;
  413.  
  414.     _sethtent(0);
  415.     while (p = _gethtent())
  416.         if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
  417.             break;
  418.     _endhtent();
  419.     return (p);
  420. }
  421.